package TEMAnalysis;


import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;

import java.awt.Dimension;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JTextField;
import java.awt.Point;
import javax.swing.JLabel;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Vector;

import javax.swing.JSlider;
import javax.swing.JList;
import javax.swing.JTextPane;
import javax.swing.JComboBox;
public class TEMAnalysis {

	private JFrame mainFrame = null;  //  @jve:decl-index=0:visual-constraint="13,5"
	private JPanel mainPanel = null;
	private JTextField hField = null;  //  @jve:decl-index=0:visual-constraint="434,124"
	private JLabel hLabel = null;  //  @jve:decl-index=0:visual-constraint="395,117"
	private JLabel kLabel = null;  //  @jve:decl-index=0:visual-constraint="474,129"
	private JTextField kField = null;  //  @jve:decl-index=0:visual-constraint="451,135"
	private JLabel lLabel = null;  //  @jve:decl-index=0:visual-constraint="425,148"
	private JTextField lField = null;  //  @jve:decl-index=0:visual-constraint="502,116"
	private JTextField sField = null;
	private JTextField tField = null;
	private JLabel tLabel = null;
	private JLabel sLabel = null;
	private JButton runButton = null;
	private File openFile = null;
	private JSlider divisorSlider = null;
	private JLabel divisorLabel = null;
	private JSlider biasSlider = null;
	private JLabel biasLabel = null;
	private JTextPane instructionPane = null;
	private BufferedImage originalImage = null;
	private BufferedImage currentImage = null;
	private JLabel iterationsLabel = null;
	private JTextField iterationsField = null;
	private ImagePanel imagePanel = null;
	private JButton saveButton = null;
	private ImageManipulator i = null;
	private JButton resetButton = null;
	private JButton filterButton = null;
	private JComboBox filterComboBox = null;
	private JButton openButton = null;
	private JTextField kernelField = null;
	private JTextField stdevField = null;
	private JLabel kernelLabel = null;
	private JLabel stdevLabel = null;
	private JButton setCurrentButton = null;
	private JButton undoButton = null;
	private ArrayList<BufferedImage> images = new ArrayList<BufferedImage>();
	private JButton histogramButton = null;
	JScrollPane scrollPane;
	/**
	 * This method initializes mainFram	
	 * 	
	 * @return javax.swing.JFrame	
	 */
	private JFrame getMainFrame() {
		if (mainFrame == null) {
			mainFrame = new JFrame();
			mainFrame.setSize(new Dimension(320, 720));
			scrollPane = new JScrollPane(getMainPanel());
			mainFrame.setContentPane(scrollPane);
			mainFrame.setTitle("TEM Analysis");
		}
		return mainFrame;
	}

	/**
	 * This method initializes mainPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getMainPanel() {
		if (mainPanel == null) {
			stdevLabel = new JLabel();
			stdevLabel.setBounds(new Rectangle(20, 783, 130, 25));
			stdevLabel.setText("Standard Deviation:");
			kernelLabel = new JLabel();
			kernelLabel.setBounds(new Rectangle(20, 751, 130, 25));
			kernelLabel.setText("Kernel Value:");
			iterationsLabel = new JLabel();
			iterationsLabel.setBounds(new Rectangle(20, 719, 130, 25));
			iterationsLabel.setText("Number of iterations:");
			biasLabel = new JLabel();
			biasLabel.setBounds(new Rectangle(228, 21, 26, 25));
			biasLabel.setText("Bias");
			divisorLabel = new JLabel();
			divisorLabel.setBounds(new Rectangle(147, 22, 40, 25));
			divisorLabel.setText("Divisor");
			sLabel = new JLabel();
			sLabel.setLocation(new Point(15, 170));
			sLabel.setSize(new Dimension(50, 25));
			sLabel.setText("s value:");
			tLabel = new JLabel();
			tLabel.setLocation(new Point(15, 135));
			tLabel.setSize(new Dimension(50, 25));
			tLabel.setText("f value:");
			mainPanel = new JPanel();
			mainPanel.setLayout(null);
			mainPanel.add(getHField());
			mainPanel.add(getHLabel());
			mainPanel.add(getKField());
			mainPanel.add(getKLabel());
			mainPanel.add(getLField());
			mainPanel.add(getLLabel());
			mainPanel.add(getSField(), null);
			mainPanel.add(getTField(), null);
			mainPanel.add(tLabel, null);
			mainPanel.add(sLabel, null);
			mainPanel.add(getRunButton(), null);
			mainPanel.add(getDivisorSlider(), null);
			mainPanel.add(divisorLabel, null);
			mainPanel.add(getBiasSlider(), null);
			mainPanel.add(biasLabel, null);
			mainPanel.add(getInstructionPane(), null);
			mainPanel.add(iterationsLabel, null);
			mainPanel.add(getIterationsField(), null);
			mainPanel.add(getSaveButton(), null);
			mainPanel.add(getResetButton(), null);
			mainPanel.add(getFilterButton(), null);
			mainPanel.add(getFilterComboBox(), null);
			mainPanel.add(getOpenButton(), null);
			mainPanel.add(getKernelField(), null);
			mainPanel.add(getStdevField(), null);
			mainPanel.add(kernelLabel, null);
			mainPanel.add(stdevLabel, null);
			mainPanel.add(getSetCurrentButton(), null);
			mainPanel.add(getUndoButton(), null);
			mainPanel.add(getHistogramButton(), null);
			mainPanel.setPreferredSize(new Dimension(300, 1077));
		}
		return mainPanel;
	}

	/**
	 * This method initializes hField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getHField() {
		if (hField == null) {
			hField = new JTextField();
			hField.setSize(new Dimension(45, 25));
			hField.setText("1");
			hField.setLocation(new Point(75, 30));
		}
		return hField;
	}

	/**
	 * This method initializes hLabel	
	 * 	
	 * @return javax.swing.JLabel	
	 */
	private JLabel getHLabel() {
		if (hLabel == null) {
			hLabel = new JLabel();
			hLabel.setText("h value: ");
			hLabel.setLocation(new Point(15, 30));
			hLabel.setSize(new Dimension(50, 25));
		}
		return hLabel;
	}

	/**
	 * This method initializes kLabel	
	 * 	
	 * @return javax.swing.JLabel	
	 */
	private JLabel getKLabel() {
		if (kLabel == null) {
			kLabel = new JLabel();
			kLabel.setText("k value: ");
			kLabel.setLocation(new Point(15, 65));
			kLabel.setSize(new Dimension(50, 25));
		}
		return kLabel;
	}

	/**
	 * This method initializes kField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getKField() {
		if (kField == null) {
			kField = new JTextField();
			kField.setSize(new Dimension(45, 25));
			kField.setText("1");
			kField.setLocation(new Point(75, 65));
		}
		return kField;
	}

	/**
	 * This method initializes lLabel	
	 * 	
	 * @return javax.swing.JLabel	
	 */
	private JLabel getLLabel() {
		if (lLabel == null) {
			lLabel = new JLabel();
			lLabel.setText("l value: ");
			lLabel.setLocation(new Point(15, 100));
			lLabel.setSize(new Dimension(50, 25));
		}
		return lLabel;
	}

	/**
	 * This method initializes lField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getLField() {
		if (lField == null) {
			lField = new JTextField();
			lField.setSize(new Dimension(45, 25));
			lField.setText("1");
			lField.setLocation(new Point(75, 100));
		}
		return lField;
	}

	/**
	 * This method initializes sField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getSField() {
		if (sField == null) {
			sField = new JTextField();
			sField.setSize(new Dimension(45, 25));
			sField.setText("0.8");
			sField.setLocation(new Point(75, 170));
		}
		return sField;
	}

	/**
	 * This method initializes tField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getTField() {
		if (tField == null) {
			tField = new JTextField();
			tField.setSize(new Dimension(45, 25));
			tField.setText("50");
			tField.setLocation(new Point(75, 135));
		}
		return tField;
	}

	/**
	 * This method initializes runButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	
	private JButton getRunButton() {
		if (runButton == null) {
			runButton = new JButton();
			runButton.setBounds(new Rectangle(13, 202, 115, 25));
			runButton.setText("Create Image");
			runButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					if(hField.getText().isEmpty() ||
							kField.getText().isEmpty() ||
							lField.getText().isEmpty() ||
							tField.getText().isEmpty() ||
							sField.getText().isEmpty()){
						System.out.println("Please provide all required information.");
						return;
					}
					int h = Integer.parseInt(hField.getText());
					int k = Integer.parseInt(kField.getText());
					int l = Integer.parseInt(lField.getText());
					if(h == 0 && k == 0 && l == 0){
						System.out.println("Impossible Miller indices -- cannot have three zeros.");
						return;
					}
					double t = Double.parseDouble(tField.getText());
					double s = Double.parseDouble(sField.getText());
					if(t < 0 || t > 100){
						System.out.println("Value entered for f is outside permitted range (0 < t < 100).");
						return;
					}
					Control c = new Control();
					long start = System.currentTimeMillis();
					c.getProjectionPlane(h, k, l, t, s);
					long end = System.currentTimeMillis();
					System.out.println("Projecting took " + (end - start)/1000 + " seconds to run");
					c.drawProjection();
					originalImage = c.image;
					i = new ImageManipulator(originalImage);
					images.add(originalImage);
					if(imagePanel == null){
						mainPanel.add(getImagePanel(), null);
						mainPanel.setPreferredSize(new Dimension(imagePanel.getWidth() + 330, 1077));
						scrollPane.setViewportView(mainPanel);
					}
					else{
						imagePanel.image = originalImage;
						imagePanel.repaint();
						imagePanel.setSize(new Dimension(imagePanel.image.getWidth() + 330, 1077));
						mainPanel.setPreferredSize(new Dimension(imagePanel.getWidth() + 330, 1077));
						scrollPane.setViewportView(mainPanel);
					}
					return;
				}
			});
		}
		return runButton;
	}

	/**
	 * This method initializes divisorSlider	
	 * 	
	 * @return javax.swing.JSlider	
	 */
	private JSlider getDivisorSlider() {
		if (divisorSlider == null) {
			divisorSlider = new JSlider();
			divisorSlider.setBounds(new Rectangle(140, 50, 59, 315));
			divisorSlider.setOrientation(SwingConstants.VERTICAL);
			divisorSlider.setPaintLabels(true);
			divisorSlider.setPaintTicks(true);
			divisorSlider.setMinimum(1);
			divisorSlider.setMaximum(20);
			divisorSlider.setMajorTickSpacing(1);
			divisorSlider.setValue(10);
			divisorSlider.addChangeListener(new javax.swing.event.ChangeListener() {
				public void stateChanged(javax.swing.event.ChangeEvent e) {
					if(!divisorSlider.getValueIsAdjusting()){
						currentImage = i.applyFilter(determineFilter((String)filterComboBox.getSelectedItem()), divisorSlider.getValue(), biasSlider.getValue(), Integer.parseInt(iterationsField.getText()));
						imagePanel.image = currentImage;
						imagePanel.repaint();
					}
				}
			});
		}
		return divisorSlider;
	}

	/**
	 * This method initializes biasSlider	
	 * 	
	 * @return javax.swing.JSlider	
	 */
	private JSlider getBiasSlider() {
		if (biasSlider == null) {
			biasSlider = new JSlider();
			biasSlider.setBounds(new Rectangle(214, 51, 60, 315));
			biasSlider.setOrientation(SwingConstants.VERTICAL);
			biasSlider.setPaintLabels(true);
			biasSlider.setPaintTicks(true);
			biasSlider.setMinimum(-100);
			biasSlider.setMaximum(100);
			biasSlider.setMajorTickSpacing(20);
			biasSlider.setMinorTickSpacing(5);
			biasSlider.setValue(0);
			biasSlider.addChangeListener(new javax.swing.event.ChangeListener() {
				public void stateChanged(javax.swing.event.ChangeEvent e) {
					if(!biasSlider.getValueIsAdjusting()){
						currentImage = i.applyFilter(determineFilter((String)filterComboBox.getSelectedItem()), divisorSlider.getValue(), biasSlider.getValue(), Integer.parseInt(iterationsField.getText()));
						imagePanel.image = currentImage;
						imagePanel.repaint();
					}
				}
			});
		}
		return biasSlider;
	}

	/**
	 * This method initializes instructionPane	
	 * 	
	 * @return javax.swing.JTextPane	
	 */
	private JTextPane getInstructionPane() {
		if (instructionPane == null) {
			instructionPane = new JTextPane();
			instructionPane.setBounds(new Rectangle(25, 512, 235, 150));
			instructionPane.setText("Enter desired parameters in text boxes above. " +
					"Select 'Create Image' to make the initial image. This will take about 20 seconds. Modify the image" +
					" by altering the sliders to the left and selecting different filters below. " +
					"Set the number of filter iterations using the text field below. To return to the original image, press" +
					" the reset button.");
			instructionPane.setEditable(false);
		}
		return instructionPane;
	}

	/**
	 * This method initializes iterationsField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getIterationsField() {
		if (iterationsField == null) {
			iterationsField = new JTextField();
			iterationsField.setBounds(new Rectangle(160, 719, 70, 25));
			iterationsField.setText("1");
		}
		return iterationsField;
	}

	/**
	 * This method initializes imagePanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private ImagePanel getImagePanel() {
		if (imagePanel == null) {
			imagePanel = new ImagePanel(originalImage);
			imagePanel.setLayout(null);
			imagePanel.setBounds(new Rectangle(300, 10, imagePanel.image.getWidth(), imagePanel.image.getHeight()));
		}
		return imagePanel;
	}

	/**
	 * This method initializes saveButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getSaveButton() {
		if (saveButton == null) {
			saveButton = new JButton();
			saveButton.setBounds(new Rectangle(13, 235, 115, 24));
			saveButton.setText("Save Image");
			saveButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					JFileChooser fileChooser = new JFileChooser();
					fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
					fileChooser.setDialogTitle("Save File");
					fileChooser.showSaveDialog(mainFrame);
					File f = fileChooser.getCurrentDirectory();
					if(currentImage == null){
						i.saveImage(f, fileChooser.getName(fileChooser.getSelectedFile()), originalImage);
					}
					else{
						i.saveImage(f, fileChooser.getName(fileChooser.getSelectedFile()), currentImage);
					}
				}
			});
		}
		return saveButton;
	}

	/**
	 * This method initializes resetButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getResetButton() {
		if (resetButton == null) {
			resetButton = new JButton();
			resetButton.setBounds(new Rectangle(13, 269, 115, 25));
			resetButton.setText("Reset");
			resetButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					imagePanel.image = originalImage;
					imagePanel.repaint();
					biasSlider.setValue(0);
					divisorSlider.setValue(10);
				}
			});
		}
		return resetButton;
	}

	/**
	 * This method initializes filterButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getFilterButton() {
		if (filterButton == null) {
			filterButton = new JButton();
			filterButton.setBounds(new Rectangle(13, 304, 115, 25));
			filterButton.setText("Apply Filter");
			filterButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					if(iterationsField.getText() == null){
						System.out.println("Please provide all required information.");
						return;
					}
					double[][] filter = determineFilter((String)filterComboBox.getSelectedItem());
					if(filter == null){
						if(kernelField.getText() == null ||
							stdevField.getText() == null){
							return;
						}
						else if(Integer.parseInt(kernelField.getText())%2 == 0){
							System.out.println("Kernel size must be an odd number.");
							return;
						}
						currentImage = i.gaussianBlur(Integer.parseInt(kernelField.getText()), Double.parseDouble(stdevField.getText()), Integer.parseInt(iterationsField.getText()));
					}
					else{
						currentImage = i.applyFilter(filter, divisorSlider.getValue(), biasSlider.getValue(), Integer.parseInt(iterationsField.getText()));
					}
					imagePanel.image = currentImage;
					imagePanel.repaint();
				}
			});
		}
		return filterButton;
	}

	/**
	 * This method initializes filterComboBox	
	 * 	
	 * @return javax.swing.JComboBox	
	 */
	private JComboBox getFilterComboBox() {
		if (filterComboBox == null) {
			String[] data = {"Blur_1", 
					"Blur_2",
					"GaussianBlur",
					"Sharpen_1", 
					"Sharpen_2", 
					"Enhance_Edges_1",
					"Enhance_Edges_2", 
					"Enhance_Edges_3", 
					"Find_Edges_1", 
					"Find_Edges_2", 
					"Find_Edges_3", 
					"Emboss"};
			filterComboBox = new JComboBox(data);
			filterComboBox.setBounds(new Rectangle(35, 675, 200, 25));
		}
		return filterComboBox;
	}

	public double[][] determineFilter(String name){
		
		if(name.equals("Blur_1")){
			return ImageManipulator.CFILTER_BLUR_1;
		}
		else if(name.equals("Blur_2")){
			return ImageManipulator.CFILTER_BLUR_2;
		}
		else if(name.equals("Sharpen_1")){
			return ImageManipulator.CFILTER_SHARPEN_1;
		}
		else if(name.equals("Sharpen_2")){
			return ImageManipulator.CFILTER_SHARPEN_2;
		}
		else if(name.equals("Enhance_Edges_1")){
			return ImageManipulator.CFILTER_EDGEENHANCE_1;
		}
		else if(name.equals("Enhance_Edges_2")){
			return ImageManipulator.CFILTER_EDGEENHANCE_2;
		}
		else if(name.equals("Enhance_Edges_3")){
			return ImageManipulator.CFILTER_EDGEENHANCE_3;
		}
		else if(name.equals("Find_Edges_1")){
			return ImageManipulator.CFILTER_FINDEDGE_1;
		}
		else if(name.equals("Find_Edges_2")){
			return ImageManipulator.CFILTER_FINDEDGE_2;
		}
		else if(name.equals("Find_Edges_3")){
			return ImageManipulator.CFILTER_FINDEDGE_3;
		}
		else if(name.equals("Emboss")){
			return ImageManipulator.CFILTER_EMBOSS;
		}
		else{
			return null;
		}
	}

	/**
	 * This method initializes openButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getOpenButton() {
		if (openButton == null) {
			openButton = new JButton();
			openButton.setBounds(new Rectangle(13, 339, 115, 25));
			openButton.setText("Open Image");
			openButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					JFileChooser fileChooser = new JFileChooser();
					fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
					fileChooser.setDialogTitle("Open File");
					fileChooser.showOpenDialog(mainFrame);
					openFile = fileChooser.getSelectedFile();
					if(openFile != null){
						try{
							originalImage = ImageIO.read(openFile);
						} catch(Exception ex){
							System.out.println(ex);
						}
					}
					else{
						System.out.println("Please provide all required information.");
						return;
					}
					if(imagePanel == null){
						mainPanel.add(getImagePanel(), null);
						mainPanel.setPreferredSize(new Dimension(imagePanel.getWidth() + 330, 1077));
						scrollPane.setViewportView(mainPanel);
						i = new ImageManipulator(originalImage);
						images.add(originalImage);
					}
					else{
						imagePanel.image = originalImage;
						imagePanel.repaint();
						imagePanel.setSize(new Dimension(imagePanel.image.getWidth() + 330, 1077));
						mainPanel.setPreferredSize(new Dimension(imagePanel.getWidth() + 330, 1077));
						scrollPane.setViewportView(mainPanel);
						i = new ImageManipulator(originalImage);
						images.add(originalImage);
					}
				}
			});
		}
		return openButton;
	}

	/**
	 * This method initializes kernelField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getKernelField() {
		if (kernelField == null) {
			kernelField = new JTextField();
			kernelField.setBounds(new Rectangle(160, 753, 70, 25));
			kernelField.setText("3");
		}
		return kernelField;
	}

	/**
	 * This method initializes stdevField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getStdevField() {
		if (stdevField == null) {
			stdevField = new JTextField();
			stdevField.setBounds(new Rectangle(160, 786, 70, 25));
			stdevField.setText("2");
		}
		return stdevField;
	}

	/**
	 * This method initializes setCurrentButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getSetCurrentButton() {
		if (setCurrentButton == null) {
			setCurrentButton = new JButton();
			setCurrentButton.setBounds(new Rectangle(13, 374, 115, 25));
			setCurrentButton.setText("Set Current");
			setCurrentButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					originalImage = currentImage;
					i.image = currentImage;
					images.add(currentImage);
				}
			});
		}
		return setCurrentButton;
	}

	/**
	 * This method initializes undoButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getUndoButton() {
		if (undoButton == null) {
			undoButton = new JButton();
			undoButton.setBounds(new Rectangle(13, 408, 115, 25));
			undoButton.setText("Undo");
			undoButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					if(images.size() <= 1){
						return;
					}
					images.remove(images.size()-1);
					i.image = images.get(images.size()-1);
					originalImage = images.get(images.size()-1);
					imagePanel.image = originalImage;
					imagePanel.repaint();
				}
			});
		}
		return undoButton;
	}

	/**
	 * This method initializes histogramButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getHistogramButton() {
		if (histogramButton == null) {
			histogramButton = new JButton();
			histogramButton.setBounds(new Rectangle(13, 443, 115, 25));
			histogramButton.setText("Histogram");
			histogramButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {

					JFileChooser fileChooser = new JFileChooser();
					fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
					fileChooser.setDialogTitle("Save File");
					fileChooser.showSaveDialog(mainFrame);
					File f = fileChooser.getCurrentDirectory();
					i.drawHistogram(f, fileChooser.getName(fileChooser.getSelectedFile()), 20);
				}
			});
		}
		return histogramButton;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		TEMAnalysis main = new TEMAnalysis();
		JFrame frame = main.getMainFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);

	}

}
